import com.alibaba.fastjson.JSONObject;

import java.sql.SQLException;
import java.util.*;

import static java.util.stream.Collectors.toList;

public class Conversion {
	private List<SQLConnection> connectionList;

	// 通过前端文件解析成Root
	public void decode(String sourceStr, Root root) {
		JSONObject jsonObject = JSONObject.parseObject(sourceStr);
		// 处理数据源
		List<Map> dataSourceList = (List<Map>) jsonObject.get(Constant.DataBaseConstant.DATA_SOURCE_LIST);
		root.setDataSourceList(dataSourceList);
		// 处理dataNode
		root.setNode(new Node());
		Map<String, Object> nodeMap = (Map<String, Object>) jsonObject.get(Constant.NodeConstant.NODE);
		traversingMap(nodeMap, root.getNode(), null);
	}

	// 通过root获取数据并且转化为json字符串
	public String encode(Root root) throws SQLException, ClassNotFoundException {
		// 建立sql连接池
		connectionList = new ArrayList<>();
		for (int i = 0; i < root.getDataSourceList().size(); i++) {
			SQLConnection connection = new SQLConnection(root.getDataSourceList().get(i));
			connectionList.add(connection);
		}
		Map<String, Object> dataMap = new HashMap<>();
		traversingNode(root.getNode(), dataMap);
		// 转换dataMap为标准json格式
		transSingleData(dataMap); 
		Object retJson = JSONObject.toJSON(dataMap);
		// 关闭数据库连接池
		connectionList.forEach(x -> x.close());
		return retJson.toString();
	}

	/**
	 * 遍历整个node
	 *
	 * @param node
	 * @param map
	 *            返回数据集
	 * @throws SQLException
	 */
	private void traversingNode(Node node, Map<String, Object> map) throws SQLException {

		List<Map<String, Object>> dataList = new ArrayList<>();
		// 数据

		if (node.getListData() != null && node.getListData().size() > 0) {
			for (Map<String, Object> data : node.getListData()) {
				List<SQLConnection> connectionList2 = connectionList.parallelStream()
						.filter(x -> x.getName().equals(data.get(Constant.NodeConstant.CONNECTION_NAME)))
						.collect(toList());
				SQLConnection connection = connectionList2.get(0);
				List<Map<String, Object>> result = connection
						.getResultMap((String) data.get(Constant.NodeConstant.SQL));
				// 根据filterList过滤 result
				List<Map<String, Object>> filterList = (List) data.get(Constant.NodeConstant.FILTER_LIST);
				result = filter(result, filterList, node);

				Map<String, Object> dataMap = new HashMap<>();
				// dataMap.put((String)
				// data.get(Constant.NodeConstant.DATA_NAME), result);
				dataMap.put(Constant.DataConstant.DATA, result);
				dataMap.put(Constant.DataConstant.NAME, data.get(Constant.NodeConstant.DATA_NAME));
				dataMap.put(Constant.NodeConstant.NODE_TYPE, data.get(Constant.NodeConstant.NODE_TYPE));
				dataList.add(dataMap);
			}
			map.put(Constant.NodeConstant.DATA_LIST, dataList);
			map.put(Constant.NodeConstant.NODE_NAME, node.getNodeName());
		}
		if (node.getChildren() != null && node.getChildren().size() > 0) {
			List<Map<String, Object>> childrenMap = new ArrayList<>();
			map.put(Constant.NodeConstant.CHILDREN, childrenMap);

			for (Node node1 : node.getChildren()) {
				Map<String, Object> tmp = new HashMap<>();
				childrenMap.add(tmp);
				traversingNode(node1, tmp);
			}
		}
	}

	/**
	 * 遍历map得到node
	 *
	 * @param map
	 * @param node
	 *            初始值为空
	 * @param parent
	 *            初始值为空
	 */
	public void traversingMap(Map<String, Object> map, Node node, Node parent) {
		node.setParent(parent);
		node.setNodeName((String) map.get(Constant.NodeConstant.NODE_NAME));
		List<Map<String, Object>> dataList = (List<Map<String, Object>>) map.get(Constant.NodeConstant.DATA_LIST);
		// 判断dataList是否为空
		if (dataList != null && dataList.size() != 0) {
			node.setListData(dataList);
		}
		// 子节点
		List<Map<String, Object>> nodeList = (List<Map<String, Object>>) map.get(Constant.NodeConstant.NODE_LIST);
		// 递归遍历整个树
		if (nodeList != null && nodeList.size() > 0) {
			node.setChildren(new ArrayList(nodeList.size()));
			for (int i = 0; i < nodeList.size(); i++) {
				node.getChildren().add(new Node());
				traversingMap((Map<String, Object>) nodeList.get(i).get(Constant.NodeConstant.NODE),
						node.getChildren().get(i), node);
			}
		}

	}

	/**
	 * @param structure
	 * @return
	 * @throws SQLException
	 * @throws ClassNotFoundException
	 */
	public String getJsonString(String structure) throws SQLException, ClassNotFoundException {
		Root root = new Root();
		root.setNode(new Node());
		Conversion conversion = new Conversion();
		conversion.decode(structure, root);
		String data = conversion.encode(root);
		return data;
	}

	// 获取父节点
	public Node getParent(Node node) {
		return node.getParent();
	}

	public Node getChild(Node node, String childName) {
		return node.getChildren().parallelStream().filter(x -> x.getNodeName().equals(childName)).collect(toList())
				.get(0);
	}

	/**
	 * 获取一列数据
	 *
	 * @param mapList
	 * @param colName
	 * @return
	 */
	public Set<Object> getColData(List<Map<String, Object>> mapList, String colName) {
		Set<Object> collection = new HashSet<>();
		for (Map<String, Object> map : mapList) {
			if (map.get(colName) != null) {
				collection.add(map.get(colName));
			}
		}
		return collection;
	}

	/**
	 * @param dataMap
	 *            元数据
	 * @param filterMap
	 *            过滤器{ colName,filterSign}
	 * @return
	 */
	public List<Map<String, Object>> filter(List<Map<String, Object>> dataMap, List<Map<String, Object>> filterMap,
			Node node) throws SQLException {
		if (filterMap != null && filterMap.size() > 0) {
			List<Map<String, Object>> returnMap = dataMap;
			for (Map<String, Object> map : filterMap) {
				final Set<Object> set = getColData2((String) map.get(Constant.OperrationConstant.FILTER_SOURCE), node);
				final Object  var1;
				Long var2=0L;
				switch ((String) map.get(Constant.OperrationConstant.FILTER_TYPE)) {
				case Constant.OperrationConstant.BIGGER_THAN:
					for (Object var3:set) {
						var2=(Long)var3;
					}
					var1=var2;
					returnMap = returnMap.parallelStream()
							.filter(x -> Long.valueOf(x.get(map.get(Constant.DataConstant.COL_NAME)).toString()) >Long.valueOf(var1.toString()) )
							.collect(toList());
					break;
				case Constant.OperrationConstant.LESS_THAN:
					for (Object var3:set) {
						var2=(Long)var3;
					}
					var1=var2;

					returnMap = returnMap.parallelStream()
							.filter(x -> Long.valueOf(x.get(map.get(Constant.DataConstant.COL_NAME)).toString()) <Long.valueOf(var1.toString()))
							.collect(toList());
					break;
				case Constant.OperrationConstant.EQUAL:
					for (Object var3:set) {
						var2=(Long)var3;
					}
					var1=var2;
					returnMap = returnMap.parallelStream().filter(x -> x.get(map.get(Constant.DataConstant.COL_NAME))
							.equals(var1)).collect(toList());
					break;
					case Constant.OperrationConstant.IN:
					returnMap = returnMap.parallelStream()
							.filter(x -> set.contains(x.get(map.get(Constant.DataConstant.COL_NAME))))
							.collect(toList());
					break;
				case Constant.OperrationConstant.NOT_IN:
					returnMap = returnMap.parallelStream()
							.filter(x -> !set.contains(x.get(Constant.DataConstant.COL_NAME))).collect(toList());
					break;
				}
			}
			return returnMap;
		} else {
			return dataMap;
		}

	}

	/**
	 * @param el
	 *            {"colName": "id" , "filterType"： "in" ,
	 *            "filterSource":"parent->dataname->colname" }
	 * @param node
	 * @return 输出一列数据
	 * @throws SQLException
	 */
	public Set<Object> getColData2(String el, Node node) throws SQLException {
		String[] array = { el };
		List<String> list = Arrays.stream(array).map(word -> word.split(Constant.OperrationConstant.NEXT))
				.flatMap(Arrays::stream).distinct().collect(toList());
		// 步数，向上多少个父节点
		// Long steps = list.parallelStream().filter(x ->
		// x.equals(Constant.OperrationConstant.PARENT)).count();
		// for (int i = 0; i < steps; i++) {
		// node = getParent(node);
		// }
		// 获取节点
		int step = 0;
		for (String var1 : list) {
			if (var1.contains(Constant.OperrationConstant.PARENT)) {
				node = getParent(node);
				step += 1;
			}
			if (var1.contains(Constant.OperrationConstant.CHILD)) {
				String[] arrays = var1.split(Constant.OperrationConstant.UNDERlINE);
				String childName = arrays[1];
				node = getChild(node, childName);
				step += 1;
			}
		}

		Map<String, Object> mapData = null;
		for (int i = 0; i < node.getListData().size(); i++) {
			if (node.getListData().get(i).get(Constant.NodeConstant.DATA_NAME).equals(list.get(step))) {
				mapData = node.getListData().get(i);
				break;
			}
		}

		SQLConnection connection = null;
		for (SQLConnection var : connectionList) {
			if (var.getName().equals(mapData.get(Constant.NodeConstant.CONNECTION_NAME))) {
				connection = var;
				break;
			}
		}
		List<Map<String, Object>> dataMap = connection.getResultMap((String) mapData.get(Constant.NodeConstant.SQL));
		Set<Object> set = getColData(dataMap, list.get(step + 1));
		return set;
	}

	/*
	 * map转换格式
	 */
	public void transSingleData(Map<String, Object> map) {
		List<Map<String, Object>> dataList = (List) map.get(Constant.NodeConstant.DATA_LIST);
		if (dataList != null && dataList.size() > 0) {
			for (Map<String, Object> obj : dataList) {
				Integer nodeType = (Integer) obj.get(Constant.NodeConstant.NODE_TYPE);
				if (nodeType.equals(0)) {
					String name = (String) obj.get(Constant.DataConstant.NAME);
					List<Map<String, Object>> var1 = (List) obj.get(Constant.DataConstant.DATA);
					Map<String, Object> var2 = var1.get(0);
					Set<String> var3 = var2.keySet();
					Object var4 = null;
					for (String key : var3) {
						var4 = var2.get(key);
					}
					map.put(name, var4);
				}
				else{
					List<Map<String, Object>> var1 = (List) obj.get(Constant.DataConstant.DATA);
					String name = (String) obj.get(Constant.DataConstant.NAME);
					map.put(name, var1);
				}
			}
			map.remove(Constant.NodeConstant.DATA_LIST);
		}
	
		List<Map<String, Object>> children = (List) map.get(Constant.NodeConstant.CHILDREN);
		if (children != null && children.size() > 0) {
			for (Map<String, Object> obj : children) {
				transSingleData(obj);
				map.put((String)obj.get(Constant.NodeConstant.NODE_NAME),obj);
				map.remove(Constant.NodeConstant.NODE_NAME);
			}
			map.remove(Constant.NodeConstant.CHILDREN);
			
		}

	}

}
